﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Text.RegularExpressions;
using FastColoredTextBoxNS;

namespace Obfuscator
{
    public partial class CodeViewer : Form
    {

        Place leftBracketPlace = new Place(-1, -1);
        Place rightBracketPlace = new Place(-1, -1);
        public CodeViewer()
        {
            InitializeComponent();

            if (MainForm.AssembliesPaths.Count != 0)
            {
                foreach (var assembliesPath in MainForm.AssembliesPaths)
                {
                    comboBoxSelect.Items.Add(assembliesPath);

                }
                comboBoxSelect.SelectedIndex = 0;
            }

            LoadingAssemblies();

        }

        private void CloseBtn_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void fastColoredTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            var sw = Stopwatch.StartNew();
            //clear style of changed range
            e.ChangedRange.ClearStyle();
            //comment highlighting
            e.ChangedRange.SetStyle(Color.Green, Color.Transparent, FontStyle.Italic, @"//.*$", RegexOptions.Multiline);
            //keyword highlighting
            e.ChangedRange.SetStyle(Color.Blue, @"\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b");
            //class name highlighting
            e.ChangedRange.SetStyle(FontStyle.Bold, @"\b(class|struct|enum)\s+(?<range>[\w_]+?)\b");
            //number highlighting
            e.ChangedRange.SetStyle(Color.Magenta, @"\b\d+[\.]?\d*([eE]\-?\d+)?[lLdDfF]?\b|\b0x[a-fA-F\d]+\b");
            //string highlighting
            e.ChangedRange.SetStyle(Color.Brown, Color.Transparent, FontStyle.Italic, @""".*?""|'.+?'");
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
            //bracket highlighting
            HighlightBrackets();
        }

        private void findToolStripMenuItem_Click(object sender, EventArgs e)
        {
            fastColoredTextBoxBefore.ShowFindDialog();
        }

        private void replaceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            fastColoredTextBoxBefore.ShowReplaceDialog();
        }

        #region Brackets highlighting

        private void HighlightBrackets()
        {
            ClearBracketsHighlight();
            //
            Range range = fastColoredTextBoxBefore.Selection.Clone();//need clone because we will move caret
            int counter = 0;
            int maxIterations = 10000;
            while (range.GoLeft())//move caret left
            {
                if (range.CharAfterStart == '{') counter++;
                if (range.CharAfterStart == '}') counter--;
                if (counter == 1)
                {
                    //found left bracket place
                    leftBracketPlace = range.Start;
                    //highlighting
                    range.End = new Place(range.Start.iChar + 1, range.Start.iLine);
                    range.SetStyle(Color.Transparent, Color.Lime);
                    break;
                }
                //
                maxIterations--;
                if (maxIterations <= 0) break;
            }
            //
            range = fastColoredTextBoxBefore.Selection.Clone();//need clone because we will move caret
            counter = 0;
            maxIterations = 10000;
            do
            {
                if (range.CharAfterStart == '{')
                    counter++;
                if (range.CharAfterStart == '}')
                    counter--;
                if (counter == -1)
                {
                    //found right bracket place
                    rightBracketPlace = range.Start;
                    //highlighting
                    range.End = new Place(range.Start.iChar + 1, range.Start.iLine);
                    range.SetStyle(Color.Transparent, Color.Lime);
                    break;
                }
                //
                maxIterations--;
                if (maxIterations <= 0) break;
            } while (range.GoRight());//move caret right
        }

        private void ClearBracketsHighlight()
        {
            if (leftBracketPlace.iLine >= 0)
                fastColoredTextBoxBefore.GetRange(leftBracketPlace, new Place(leftBracketPlace.iChar + 1, leftBracketPlace.iLine)).ClearStyle();
            if (rightBracketPlace.iLine >= 0)
                fastColoredTextBoxBefore.GetRange(rightBracketPlace, new Place(rightBracketPlace.iChar + 1, rightBracketPlace.iLine)).ClearStyle();

            leftBracketPlace = new Place(-1, -1);
            rightBracketPlace = new Place(-1, -1);
        }

        private void fastColoredTextBox_TextChanging(object sender, EventArgs e)
        {
            //clear brackets highlighting before text change
            ClearBracketsHighlight();
        }

        private void fastColoredTextBox_SelectionChanged(object sender, EventArgs e)
        {
            //brackets highlighting after selection changed
            HighlightBrackets();
        }
        #endregion


        private void SelectedIndexChanged_SelectComboBox(object sender, EventArgs e)
        {
          //  string document = (sender as ComboBox).SelectedItem.ToString();

            LoadingAssemblies();
        }


        private void LoadingAssemblies()
        {
            SharpDecompiler sharpDecompilerAfter = new SharpDecompiler(ObfuscatorSettings.OUTPUT_PATH + "\\Obfuscated." + comboBoxSelect.SelectedItem.ToString());
            sharpDecompilerAfter.DecompileAssembly();
            fastColoredTextBoxAfter.Text = sharpDecompilerAfter.DecompiledCode;

            SharpDecompiler sharpDecompilerBefore = new SharpDecompiler(ObfuscatorSettings.OUTPUT_PATH + "\\" + comboBoxSelect.SelectedItem.ToString());
            sharpDecompilerBefore.DecompileAssembly();
            fastColoredTextBoxBefore.Text = sharpDecompilerBefore.DecompiledCode;

        }


    }
}



